package com.aura.common.redis.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * 分布式锁封装类（基于 Redisson）
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class RedissonLockService {

    private final RedissonClient redissonClient;

    /**
     * 获取锁（阻塞式，设置锁自动释放时间）
     *
     * @param lockKey 锁的唯一标识（建议格式：模块名:业务ID）
     * @param expire 锁的超时时间（单位毫秒），传 -1 表示开启 WatchDog 自动续期
     * @return RLock 实例（失败返回 null）
     */
    public RLock acquire(String lockKey, long expire) {
        try {
            RLock lock = redissonClient.getLock(lockKey);
            lock.lock(expire, TimeUnit.MILLISECONDS);
            return lock;
        } catch (Exception e) {
            log.warn("获取分布式锁失败，key：{}，原因：{}", lockKey, e.getMessage());
            return null;
        }
    }

    /**
     * 获取锁（非阻塞 + 限时尝试）
     *
     * @param lockKey 锁的唯一标识
     * @param waitTime 等待时间（单位毫秒）
     * @param leaseTime 锁的持有时间（单位毫秒）
     * @return RLock 实例（获取失败返回 null）
     */
    public RLock tryAcquire(String lockKey, long waitTime, long leaseTime) {
        try {
            RLock lock = redissonClient.getLock(lockKey);
            boolean acquired = lock.tryLock(waitTime, leaseTime, TimeUnit.MILLISECONDS);
            return acquired ? lock : null;
        } catch (Exception e) {
            log.warn("尝试获取分布式锁失败，key：{}，原因：{}", lockKey, e.getMessage());
            return null;
        }
    }

    /**
     * 释放锁（要求必须是当前线程持有）
     *
     * @param lock 锁实例
     * @return true=释放成功；false=释放失败
     */
    public boolean release(RLock lock) {
        if (lock != null && lock.isHeldByCurrentThread()) {
            try {
                lock.unlock();
                return true;
            } catch (Exception e) {
                log.warn("释放分布式锁失败，原因：{}", e.getMessage());
            }
        }
        return false;
    }

}
